
package com.example.paper.common.datam.utils;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * 缓存
 * @author Long Fengfan, 2020年03月24日

 * @param <K> key
 * @param <V> value
 */
public class LRUCache<K, V> {

    private static final float LOAD_FACTORY = 0.75f;

    private final int cacheSize;

    private LinkedHashMap<K, V> map;

    /**
     * 构造
     * @param cacheSize   缓存大小
     * @param accessOrder true LRU, false FIFO
     */
    public LRUCache(int cacheSize, boolean accessOrder) {
        this.cacheSize = cacheSize;

        //LinkedHashMap 元素大于 capacity * loadFactor 的时候，就会自动进行两倍扩容
        //为使缓存大小不会进行自动扩容，初始化大小设置为 (CACHE_SIZE / loadFactor) + 1
        int initialCapacity = (int) Math.ceil(this.cacheSize / LOAD_FACTORY) + 1;
        map = new LinkedHashMap<K, V>(initialCapacity, LOAD_FACTORY, accessOrder) {
            @Override
            protected boolean removeEldestEntry(Map.Entry eldest) {
                return size() > LRUCache.this.cacheSize;
            }
        };
    }

    /**
     * put
     * @param key key
     * @param value value
     */
    public synchronized void put(K key, V value) {
        map.put(key, value);
    }


    /**
     * get
     * @param key key
     * @return V
     */
    public synchronized V get(K key) {
        return map.get(key);
    }


    /**
     * clear
     */
    public synchronized void clear() {
        map.clear();
    }


    /**
     * size
     * @return int
     */
    public synchronized int size() {
        return map.size();
    }


    /**
     * remove
     * @param key key
     */
    public synchronized void remove(K key) {
        map.remove(key);
    }


    /**
     * getAll
     * @return Set
     */
    public synchronized Set<Map.Entry<K, V>> getAll() {
        return map.entrySet();
    }

    /**
     * putIfAbsent
     * @return 旧值，之前无为null
     */
    public synchronized V putIfAbsent(K key, V value) {
        return map.putIfAbsent(key, value);
    }

}
